Public Class StatsDataAccess
    Public Structure Filters
        Dim BaseUrl As String
        Dim BossName As String
        Dim AreaName As String
        Dim CharaClass As String
        Dim CharaName As String
        Dim DamageOut As Boolean
        Dim DamageIn As Boolean
        Dim Heal As Boolean
    End Structure

    Public Sub Export(ByRef Raids As RaidData(), Optional ByVal Filename As String = "C:\temp\StatsData.xml")
        Dim XmlUtil As New XmlUtils.AccessXml

        XmlUtil.ExportByXml(Raids, Filename)
    End Sub

    Public Sub Import(ByRef Raids As RaidData(), Optional ByVal Filename As String = "C:\temp\StatsData.xml")
        Dim XmlUtil As New XmlUtils.AccessXml

        XmlUtil.ImportFromXml(Raids, Filename)
    End Sub

    Public Function CopyRaidData(ByRef RaidFrom As RaidData(), ByRef RaidTo As RaidData(), ByVal Filter As StatsDataAccess.Filters) As RaidData()

        If RaidFrom Is Nothing Then
            RaidTo = Nothing
            Return Nothing
        End If

        Dim r As Long
        Dim r2 As Long = -1
        For r = 0 To RaidFrom.Length - 1
            If RaidFrom(r).Bosses IsNot Nothing Then
                If Filter.BaseUrl = "*" Or Filter.BaseUrl = RaidFrom(r).BaseUrl Then
                    r2 += 1
                    ReDim Preserve RaidTo(r2)
                    RaidTo(r2) = New RaidData

                    RaidTo(r2).BaseUrl = RaidFrom(r).BaseUrl
                    RaidTo(r2).Region = RaidFrom(r).Region
                    RaidTo(r2).Realm = RaidFrom(r).Realm
                    RaidTo(r2).RaidName = RaidFrom(r).RaidName
                    RaidTo(r2).LastUpdate = RaidFrom(r).LastUpdate

                    Dim b As Long
                    Dim b2 As Long = -1
                    For b = 0 To RaidFrom(r).Bosses.Length - 1
                        If (Filter.BossName = "*" Or Filter.BossName = RaidFrom(r).Bosses(b).Boss) _
                                And (Filter.AreaName = "*" Or Filter.AreaName = RaidFrom(r).Bosses(b).Area) Then

                            Dim ExistRaid As Boolean = False

                            If RaidFrom(r).Bosses(b).Characters IsNot Nothing Then
                                Dim c As Long
                                For c = 0 To RaidFrom(r).Bosses(b).Characters.Length - 1
                                    If (Filter.CharaClass = "*" Or Filter.CharaClass = RaidFrom(r).Bosses(b).Characters(c).CharaClass) _
                                            And (Filter.CharaName = "*" Or Filter.CharaName = RaidFrom(r).Bosses(b).Characters(c).CharaName) Then

                                        ExistRaid = ExistRaid Or (Filter.Heal And RaidFrom(r).Bosses(b).Characters(c).Heals IsNot Nothing)
                                        ExistRaid = ExistRaid Or (Filter.DamageOut And RaidFrom(r).Bosses(b).Characters(c).DamageOut IsNot Nothing)
                                        ExistRaid = ExistRaid Or (Filter.DamageIn And RaidFrom(r).Bosses(b).Characters(c).DamageIn IsNot Nothing)
                                    End If

                                    If ExistRaid Then Exit For
                                Next
                            End If

                            If ExistRaid Then
                                b2 += 1
                                ReDim Preserve RaidTo(r2).Bosses(b2)
                                RaidTo(r2).Bosses(b2) = New BossData

                                RaidTo(r2).Bosses(b2).Dir = RaidFrom(r).Bosses(b).Dir
                                RaidTo(r2).Bosses(b2).RaidDate = RaidFrom(r).Bosses(b).RaidDate
                                RaidTo(r2).Bosses(b2).Boss = RaidFrom(r).Bosses(b).Boss
                                RaidTo(r2).Bosses(b2).Area = RaidFrom(r).Bosses(b).Area
                                RaidTo(r2).Bosses(b2).Duration = RaidFrom(r).Bosses(b).Duration

                                RaidTo(r2).Bosses(b2).RaidDmgOut = RaidFrom(r).Bosses(b).RaidDmgOut
                                RaidTo(r2).Bosses(b2).RaidDmgIn = RaidFrom(r).Bosses(b).RaidDmgIn
                                RaidTo(r2).Bosses(b2).RaidHeal = RaidFrom(r).Bosses(b).RaidHeal
                                RaidTo(r2).Bosses(b2).RaidEffHeal = RaidFrom(r).Bosses(b).RaidEffHeal
                                RaidTo(r2).Bosses(b2).RaidDispel = RaidFrom(r).Bosses(b).RaidDispel
                                RaidTo(r2).Bosses(b2).RaidDeath = RaidFrom(r).Bosses(b).RaidDeath

                                RaidTo(r2).Bosses(b2).Attempt = RaidFrom(r).Bosses(b).Attempt
                                RaidTo(r2).Bosses(b2).Killed = RaidFrom(r).Bosses(b).Killed


                                Dim ExistHeal As Boolean = False
                                Dim ExistDmgOut As Boolean = False
                                Dim ExistDmgIn As Boolean = False

                                Dim c As Long
                                Dim c2 As Long = -1
                                For c = 0 To RaidFrom(r).Bosses(b).Characters.Length - 1
                                    If (Filter.CharaClass = "*" Or Filter.CharaClass = RaidFrom(r).Bosses(b).Characters(c).CharaClass) _
                                            And (Filter.CharaName = "*" Or Filter.CharaName = RaidFrom(r).Bosses(b).Characters(c).CharaName) Then

                                        ExistHeal = Filter.Heal And RaidFrom(r).Bosses(b).Characters(c).Heals IsNot Nothing
                                        ExistDmgOut = Filter.DamageOut And RaidFrom(r).Bosses(b).Characters(c).DamageOut IsNot Nothing
                                        ExistDmgIn = Filter.DamageIn And RaidFrom(r).Bosses(b).Characters(c).DamageIn IsNot Nothing

                                        c2 += 1
                                        ReDim Preserve RaidTo(r2).Bosses(b2).Characters(c2)
                                        RaidTo(r2).Bosses(b2).Characters(c2) = New CharaData

                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaName = RaidFrom(r).Bosses(b).Characters(c).CharaName
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaID = RaidFrom(r).Bosses(b).Characters(c).CharaID
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaClass = RaidFrom(r).Bosses(b).Characters(c).CharaClass
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaBuild = RaidFrom(r).Bosses(b).Characters(c).CharaBuild
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaPres = RaidFrom(r).Bosses(b).Characters(c).CharaPres
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaAct = RaidFrom(r).Bosses(b).Characters(c).CharaAct

                                        RaidTo(r2).Bosses(b2).Characters(c2).DmgOutRate = RaidFrom(r).Bosses(b).Characters(c).DmgOutRate
                                        RaidTo(r2).Bosses(b2).Characters(c2).DmgInRate = RaidFrom(r).Bosses(b).Characters(c).DmgInRate
                                        RaidTo(r2).Bosses(b2).Characters(c2).EffHealRate = RaidFrom(r).Bosses(b).Characters(c).EffHealRate

                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaDmgOut = RaidFrom(r).Bosses(b).Characters(c).CharaDmgOut
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaDmgIn = RaidFrom(r).Bosses(b).Characters(c).CharaDmgIn
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaHeal = RaidFrom(r).Bosses(b).Characters(c).CharaHeal
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaEffHeal = RaidFrom(r).Bosses(b).Characters(c).CharaEffHeal
                                        RaidTo(r2).Bosses(b2).Characters(c2).OverHeal = RaidFrom(r).Bosses(b).Characters(c).OverHeal

                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaDispel = RaidFrom(r).Bosses(b).Characters(c).CharaDispel
                                        RaidTo(r2).Bosses(b2).Characters(c2).CharaDeath = RaidFrom(r).Bosses(b).Characters(c).CharaDeath

                                        If ExistHeal Then
                                            Dim s As Long
                                            Dim s2 As Long = -1
                                            For s = 0 To RaidFrom(r).Bosses(b).Characters(c).Heals.Length - 1
                                                s2 += 1
                                                ReDim Preserve RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2)
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2) = New HealData

                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).SpellName = RaidFrom(r).Bosses(b).Characters(c).Heals(s).SpellName
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).Casts = RaidFrom(r).Bosses(b).Characters(c).Heals(s).Casts
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).Heal = RaidFrom(r).Bosses(b).Characters(c).Heals(s).Heal
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).EffHeal = RaidFrom(r).Bosses(b).Characters(c).Heals(s).EffHeal
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).EffHealRate = RaidFrom(r).Bosses(b).Characters(c).Heals(s).EffHealRate

                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).Hits = RaidFrom(r).Bosses(b).Characters(c).Heals(s).Hits
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).Crits = RaidFrom(r).Bosses(b).Characters(c).Heals(s).Crits
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).Ticks = RaidFrom(r).Bosses(b).Characters(c).Heals(s).Ticks

                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).AveHit = RaidFrom(r).Bosses(b).Characters(c).Heals(s).AveHit
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).AveCrit = RaidFrom(r).Bosses(b).Characters(c).Heals(s).AveCrit
                                                RaidTo(r2).Bosses(b2).Characters(c2).Heals(s2).AveTick = RaidFrom(r).Bosses(b).Characters(c).Heals(s).AveTick
                                            Next
                                        End If

                                        If ExistDmgOut Then
                                            Dim s As Long
                                            Dim s2 As Long = -1
                                            For s = 0 To RaidFrom(r).Bosses(b).Characters(c).DamageOut.Length - 1
                                                s2 += 1
                                                ReDim Preserve RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2)
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2) = New DpsData

                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).SpellName = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).SpellName
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).Target = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).Target
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).Casts = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).Casts
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).Damage = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).Damage
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).DamageRate = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).DamageRate

                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).Hits = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).Hits
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).Crits = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).Crits
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).Ticks = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).Ticks

                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveHit = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).AveHit
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveCrit = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).AveCrit
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveTick = RaidFrom(r).Bosses(b).Characters(c).DamageOut(s).AveTick
                                            Next
                                        End If

                                        If ExistDmgIn Then
                                            Dim s As Long
                                            Dim s2 As Long = -1
                                            For s = 0 To RaidFrom(r).Bosses(b).Characters(c).DamageIn.Length - 1
                                                s2 += 1
                                                ReDim Preserve RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2)
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2) = New DpsData

                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).SpellName = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).SpellName
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).Target = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).Target
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).Casts = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).Casts
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).Damage = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).Damage
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).DamageRate = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).DamageRate

                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).Hits = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).Hits
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).Crits = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).Crits
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).Ticks = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).Ticks

                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveHit = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).AveHit
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveCrit = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).AveCrit
                                                RaidTo(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveTick = RaidFrom(r).Bosses(b).Characters(c).DamageIn(s).AveTick
                                            Next
                                        End If
                                    End If
                                Next
                            End If
                        End If
                    Next
                End If
            End If
        Next

        Return RaidTo
    End Function

    Public Function CalcurateCharaReport(ByRef RaidSource As RaidData(), ByRef RaidResult As RaidData()) As RaidData()

        If RaidSource Is Nothing Then
            RaidResult = Nothing
            Return Nothing
        End If

        Dim i As Long
        Dim r As Long
        Dim r2 As Long = -1
        For r = 0 To RaidSource.Length - 1
            If RaidSource(r).Bosses IsNot Nothing Then
                r2 += 1
                ReDim Preserve RaidResult(r2)
                RaidResult(r2) = New RaidData

                RaidResult(r2).BaseUrl = RaidSource(r).BaseUrl
                RaidResult(r2).Region = RaidSource(r).Region
                RaidResult(r2).Realm = RaidSource(r).Realm
                RaidResult(r2).RaidName = RaidSource(r).RaidName
                RaidResult(r2).LastUpdate = RaidSource(r).LastUpdate

                Dim b As Long
                Dim b2 As Long = -1
                For b = 0 To RaidSource(r).Bosses.Length - 1

                    Dim ExistRaid As Boolean = False

                    If RaidSource(r).Bosses(b).Characters IsNot Nothing Then
                        Dim c As Long
                        For c = 0 To RaidSource(r).Bosses(b).Characters.Length - 1
                            ExistRaid = ExistRaid Or (RaidSource(r).Bosses(b).Characters(c).Heals IsNot Nothing)
                            ExistRaid = ExistRaid Or (RaidSource(r).Bosses(b).Characters(c).DamageOut IsNot Nothing)
                            ExistRaid = ExistRaid Or (RaidSource(r).Bosses(b).Characters(c).DamageIn IsNot Nothing)
                            If ExistRaid Then Exit For
                        Next
                    End If

                    If ExistRaid Then

                        b2 = -1
                        If RaidResult(r2).Bosses Is Nothing Then
                            b2 = 0
                            ReDim Preserve RaidResult(r2).Bosses(b2)
                            RaidResult(r2).Bosses(b2) = New BossData
                        Else
                            For i = 0 To RaidResult(r2).Bosses.Length - 1
                                If RaidResult(r2).Bosses(i).Boss = RaidSource(r).Bosses(b).Boss Then
                                    b2 = i
                                    Exit For
                                End If
                            Next
                            If b2 < 0 Then
                                b2 = RaidResult(r2).Bosses.Length
                                ReDim Preserve RaidResult(r2).Bosses(b2)
                                RaidResult(r2).Bosses(b2) = New BossData
                            End If
                        End If

                        RaidResult(r2).Bosses(b2).Dir = RaidSource(r).Bosses(b).Dir
                        RaidResult(r2).Bosses(b2).RaidDate = RaidSource(r).Bosses(b).RaidDate
                        RaidResult(r2).Bosses(b2).Boss = RaidSource(r).Bosses(b).Boss
                        RaidResult(r2).Bosses(b2).Area = RaidSource(r).Bosses(b).Area
                        RaidResult(r2).Bosses(b2).Duration += RaidSource(r).Bosses(b).Duration

                        RaidResult(r2).Bosses(b2).RaidDmgOut = RaidSource(r).Bosses(b).RaidDmgOut
                        RaidResult(r2).Bosses(b2).RaidDmgIn += RaidSource(r).Bosses(b).RaidDmgIn
                        RaidResult(r2).Bosses(b2).RaidHeal += RaidSource(r).Bosses(b).RaidHeal
                        RaidResult(r2).Bosses(b2).RaidEffHeal += RaidSource(r).Bosses(b).RaidEffHeal
                        RaidResult(r2).Bosses(b2).RaidDispel += RaidSource(r).Bosses(b).RaidDispel
                        RaidResult(r2).Bosses(b2).RaidDeath += RaidSource(r).Bosses(b).RaidDeath

                        RaidResult(r2).Bosses(b2).Attempt += RaidSource(r).Bosses(b).Attempt
                        RaidResult(r2).Bosses(b2).Killed += RaidSource(r).Bosses(b).Killed


                        Dim ExistHeal As Boolean = False
                        Dim ExistDmgOut As Boolean = False
                        Dim ExistDmgIn As Boolean = False

                        Dim c As Long
                        Dim c2 As Long = -1
                        For c = 0 To RaidSource(r).Bosses(b).Characters.Length - 1

                            ExistHeal = RaidSource(r).Bosses(b).Characters(c).Heals IsNot Nothing
                            ExistDmgOut = RaidSource(r).Bosses(b).Characters(c).DamageOut IsNot Nothing
                            ExistDmgIn = RaidSource(r).Bosses(b).Characters(c).DamageIn IsNot Nothing

                            c2 = -1
                            If RaidResult(r2).Bosses(b2).Characters Is Nothing Then
                                c2 = 0
                                ReDim Preserve RaidResult(r2).Bosses(b2).Characters(c2)
                                RaidResult(r2).Bosses(b2).Characters(c2) = New CharaData
                            Else
                                For i = 0 To RaidResult(r2).Bosses(b2).Characters.Length - 1
                                    If RaidResult(r2).Bosses(b2).Characters(i).CharaName = RaidSource(r).Bosses(b).Characters(c).CharaName Then
                                        c2 = i
                                        Exit For
                                    End If
                                Next
                                If c2 < 0 Then
                                    c2 = RaidResult(r2).Bosses(b2).Characters.Length
                                    ReDim Preserve RaidResult(r2).Bosses(b2).Characters(c2)
                                    RaidResult(r2).Bosses(b2).Characters(c2) = New CharaData
                                End If
                            End If

                            RaidResult(r2).Bosses(b2).Characters(c2).CharaName = RaidSource(r).Bosses(b).Characters(c).CharaName
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaID = RaidSource(r).Bosses(b).Characters(c).CharaID
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaClass = RaidSource(r).Bosses(b).Characters(c).CharaClass
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaBuild = RaidSource(r).Bosses(b).Characters(c).CharaBuild
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaPres += RaidSource(r).Bosses(b).Characters(c).CharaPres
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaAct += RaidSource(r).Bosses(b).Characters(c).CharaAct

                            RaidResult(r2).Bosses(b2).Characters(c2).CharaDmgOut += RaidSource(r).Bosses(b).Characters(c).CharaDmgOut
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaDmgIn += RaidSource(r).Bosses(b).Characters(c).CharaDmgIn
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaHeal += RaidSource(r).Bosses(b).Characters(c).CharaHeal
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaEffHeal += RaidSource(r).Bosses(b).Characters(c).CharaEffHeal
                            If RaidResult(r2).Bosses(b2).Characters(c2).CharaHeal = 0 Then
                                RaidResult(r2).Bosses(b2).Characters(c2).OverHeal = 0
                            Else
                                RaidResult(r2).Bosses(b2).Characters(c2).OverHeal = Math.Round((1 - RaidResult(r2).Bosses(b2).Characters(c2).CharaEffHeal / RaidResult(r2).Bosses(b2).Characters(c2).CharaHeal) * 100, 2)
                            End If

                            If RaidResult(r2).Bosses(b2).RaidDmgOut = 0 Then
                                RaidResult(r2).Bosses(b2).Characters(c2).DmgOutRate = 0
                            Else
                                RaidResult(r2).Bosses(b2).Characters(c2).DmgOutRate = Math.Round(RaidResult(r2).Bosses(b2).Characters(c2).CharaDmgOut / RaidResult(r2).Bosses(b2).RaidDmgOut * 100, 2)
                            End If
                            If RaidResult(r2).Bosses(b2).RaidDmgIn = 0 Then
                                RaidResult(r2).Bosses(b2).Characters(c2).DmgInRate = 0
                            Else
                                RaidResult(r2).Bosses(b2).Characters(c2).DmgInRate = Math.Round(RaidResult(r2).Bosses(b2).Characters(c2).CharaDmgIn / RaidResult(r2).Bosses(b2).RaidDmgIn * 100, 2)
                            End If
                            If RaidResult(r2).Bosses(b2).RaidEffHeal = 0 Then
                                RaidResult(r2).Bosses(b2).Characters(c2).EffHealRate = 0
                            Else
                                RaidResult(r2).Bosses(b2).Characters(c2).EffHealRate = Math.Round(RaidResult(r2).Bosses(b2).Characters(c2).CharaEffHeal / RaidResult(r2).Bosses(b2).RaidEffHeal * 100, 2)
                            End If

                            RaidResult(r2).Bosses(b2).Characters(c2).CharaDispel += RaidSource(r).Bosses(b).Characters(c).CharaDispel
                            RaidResult(r2).Bosses(b2).Characters(c2).CharaDeath += RaidSource(r).Bosses(b).Characters(c).CharaDeath

                            If ExistHeal Then
                                Dim s As Long
                                For s = 0 To RaidSource(r).Bosses(b).Characters(c).Heals.Length - 1
                                    Dim s2 As Long = -1
                                    If RaidResult(r2).Bosses(b2).Characters(c2).Heals Is Nothing Then
                                        s2 = 0
                                        ReDim Preserve RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2)
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2) = New HealData
                                    Else
                                        For i = 0 To RaidResult(r2).Bosses(b2).Characters(c2).Heals.Length - 1
                                            If RaidResult(r2).Bosses(b2).Characters(c2).Heals(i).SpellName = RaidSource(r).Bosses(b).Characters(c).Heals(s).SpellName Then
                                                s2 = i
                                                Exit For
                                            End If
                                        Next
                                        If s2 < 0 Then
                                            s2 = RaidResult(r2).Bosses(b2).Characters(c2).Heals.Length
                                            ReDim Preserve RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2)
                                            RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2) = New HealData
                                        End If
                                    End If

                                    RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).SpellName = RaidSource(r).Bosses(b).Characters(c).Heals(s).SpellName

                                    Dim TotHit As Single = RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveHit * RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Hits + RaidSource(r).Bosses(b).Characters(c).Heals(s).AveHit * RaidSource(r).Bosses(b).Characters(c).Heals(s).Hits
                                    Dim TotCrit As Single = RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveCrit * RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Crits + RaidSource(r).Bosses(b).Characters(c).Heals(s).AveCrit * RaidSource(r).Bosses(b).Characters(c).Heals(s).Crits
                                    Dim TotTick As Single = RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveTick * RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Ticks + RaidSource(r).Bosses(b).Characters(c).Heals(s).AveTick * RaidSource(r).Bosses(b).Characters(c).Heals(s).Ticks

                                    RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Casts += RaidSource(r).Bosses(b).Characters(c).Heals(s).Casts
                                    RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Heal += RaidSource(r).Bosses(b).Characters(c).Heals(s).Heal
                                    RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).EffHeal += RaidSource(r).Bosses(b).Characters(c).Heals(s).EffHeal
                                    If RaidResult(r2).Bosses(b2).Characters(c2).CharaEffHeal = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).EffHealRate = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).EffHealRate = Math.Round(RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).EffHeal / RaidResult(r2).Bosses(b2).Characters(c2).CharaEffHeal * 100, 2)
                                    End If

                                    RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Hits += RaidSource(r).Bosses(b).Characters(c).Heals(s).Hits
                                    RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Crits += RaidSource(r).Bosses(b).Characters(c).Heals(s).Crits
                                    RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Ticks += RaidSource(r).Bosses(b).Characters(c).Heals(s).Ticks

                                    If RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Hits = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveHit = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveHit = TotHit / RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Hits
                                    End If
                                    If RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Crits = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveCrit = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveCrit = TotCrit / RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Crits
                                    End If
                                    If RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Ticks = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveTick = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).AveTick = TotTick / RaidResult(r2).Bosses(b2).Characters(c2).Heals(s2).Ticks
                                    End If
                                Next
                            End If

                            If ExistDmgOut Then
                                Dim s As Long
                                For s = 0 To RaidSource(r).Bosses(b).Characters(c).DamageOut.Length - 1
                                    Dim s2 As Long = -1
                                    If RaidResult(r2).Bosses(b2).Characters(c2).DamageOut Is Nothing Then
                                        s2 = 0
                                        ReDim Preserve RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2)
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2) = New DpsData
                                    Else
                                        For i = 0 To RaidResult(r2).Bosses(b2).Characters(c2).DamageOut.Length - 1
                                            If RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(i).SpellName = RaidSource(r).Bosses(b).Characters(c).DamageOut(s).SpellName _
                                                    And RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(i).Target = RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Target Then
                                                s2 = i
                                                Exit For
                                            End If
                                        Next
                                        If s2 < 0 Then
                                            s2 = RaidResult(r2).Bosses(b2).Characters(c2).DamageOut.Length
                                            ReDim Preserve RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2)
                                            RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2) = New DpsData
                                        End If
                                    End If

                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).SpellName = RaidSource(r).Bosses(b).Characters(c).DamageOut(s).SpellName
                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Target = RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Target

                                    Dim TotHit As Single = RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveHit * RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Hits + RaidSource(r).Bosses(b).Characters(c).DamageOut(s).AveHit * RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Hits
                                    Dim TotCrit As Single = RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveCrit * RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Crits + RaidSource(r).Bosses(b).Characters(c).DamageOut(s).AveCrit * RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Crits
                                    Dim TotTick As Single = RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveTick * RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Ticks + RaidSource(r).Bosses(b).Characters(c).DamageOut(s).AveTick * RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Ticks

                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Casts += RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Casts
                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Damage += RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Damage
                                    If RaidResult(r2).Bosses(b2).Characters(c2).CharaDmgOut = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).DamageRate = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).DamageRate = Math.Round(RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Damage / RaidResult(r2).Bosses(b2).Characters(c2).CharaDmgOut * 100, 2)
                                    End If

                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Hits += RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Hits
                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Crits += RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Crits
                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Ticks += RaidSource(r).Bosses(b).Characters(c).DamageOut(s).Ticks

                                    If RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Hits = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveHit = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveHit = TotHit / RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Hits
                                    End If
                                    If RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Crits = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveCrit = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveCrit = TotCrit / RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Crits
                                    End If
                                    If RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Ticks = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveTick = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).AveTick = TotTick / RaidResult(r2).Bosses(b2).Characters(c2).DamageOut(s2).Ticks
                                    End If
                                Next
                            End If

                            If ExistDmgIn Then
                                Dim s As Long
                                For s = 0 To RaidSource(r).Bosses(b).Characters(c).DamageIn.Length - 1
                                    Dim s2 As Long = -1
                                    If RaidResult(r2).Bosses(b2).Characters(c2).DamageIn Is Nothing Then
                                        s2 = 0
                                        ReDim Preserve RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2)
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2) = New DpsData
                                    Else
                                        For i = 0 To RaidResult(r2).Bosses(b2).Characters(c2).DamageIn.Length - 1
                                            If RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(i).SpellName = RaidSource(r).Bosses(b).Characters(c).DamageIn(s).SpellName _
                                                    And RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(i).Target = RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Target Then
                                                s2 = i
                                                Exit For
                                            End If
                                        Next
                                        If s2 < 0 Then
                                            s2 = RaidResult(r2).Bosses(b2).Characters(c2).DamageIn.Length
                                            ReDim Preserve RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2)
                                            RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2) = New DpsData
                                        End If
                                    End If

                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).SpellName = RaidSource(r).Bosses(b).Characters(c).DamageIn(s).SpellName
                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Target = RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Target

                                    Dim TotHit As Single = RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveHit * RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Hits + RaidSource(r).Bosses(b).Characters(c).DamageIn(s).AveHit * RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Hits
                                    Dim TotCrit As Single = RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveCrit * RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Crits + RaidSource(r).Bosses(b).Characters(c).DamageIn(s).AveCrit * RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Crits
                                    Dim TotTick As Single = RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveTick * RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Ticks + RaidSource(r).Bosses(b).Characters(c).DamageIn(s).AveTick * RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Ticks

                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Casts += RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Casts
                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Damage += RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Damage
                                    If RaidResult(r2).Bosses(b2).Characters(c2).CharaDmgIn = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).DamageRate = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).DamageRate = Math.Round(RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Damage / RaidResult(r2).Bosses(b2).Characters(c2).CharaDmgIn * 100, 2)
                                    End If

                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Hits += RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Hits
                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Crits += RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Crits
                                    RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Ticks += RaidSource(r).Bosses(b).Characters(c).DamageIn(s).Ticks

                                    If RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Hits = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveHit = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveHit = TotHit / RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Hits
                                    End If
                                    If RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Crits = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveCrit = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveCrit = TotCrit / RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Crits
                                    End If
                                    If RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Ticks = 0 Then
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveTick = 0
                                    Else
                                        RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).AveTick = TotTick / RaidResult(r2).Bosses(b2).Characters(c2).DamageIn(s2).Ticks
                                    End If
                                Next
                            End If
                        Next
                    End If
                Next
            End If
        Next

        Return UpdateRates(RaidResult)
    End Function

    Public Function UpdateRates(ByRef Raids As RaidData()) As RaidData()
        If Raids Is Nothing Then
            Return Nothing
        End If

        Dim r As Long

        For r = 0 To Raids.Length - 1
            If Raids(r).Bosses IsNot Nothing Then
                Dim b As Long
                For b = 0 To Raids(r).Bosses.Length - 1

                    If Raids(r).Bosses(b).Attempt <= 0 Then
                        Raids(r).Bosses(b).Attempt = 0
                    End If

                    Dim ExistHeal As Boolean = False
                    Dim ExistDmgOut As Boolean = False
                    Dim ExistDmgIn As Boolean = False

                    Dim c As Long
                    For c = 0 To Raids(r).Bosses(b).Characters.Length - 1

                        ExistHeal = Raids(r).Bosses(b).Characters(c).Heals IsNot Nothing
                        ExistDmgOut = Raids(r).Bosses(b).Characters(c).DamageOut IsNot Nothing
                        ExistDmgIn = Raids(r).Bosses(b).Characters(c).DamageIn IsNot Nothing

                        If Raids(r).Bosses(b).Characters(c).CharaHeal = 0 Then
                            Raids(r).Bosses(b).Characters(c).OverHeal = 0
                        Else
                            Raids(r).Bosses(b).Characters(c).OverHeal = Math.Round((1 - Raids(r).Bosses(b).Characters(c).CharaEffHeal / Raids(r).Bosses(b).Characters(c).CharaHeal) * 100, 2)
                        End If

                        If Raids(r).Bosses(b).RaidDmgOut = 0 Then
                            Raids(r).Bosses(b).Characters(c).DmgOutRate = 0
                        Else
                            Raids(r).Bosses(b).Characters(c).DmgOutRate = Math.Round(Raids(r).Bosses(b).Characters(c).CharaDmgOut / Raids(r).Bosses(b).RaidDmgOut * 100, 2)
                        End If
                        If Raids(r).Bosses(b).RaidDmgIn = 0 Then
                            Raids(r).Bosses(b).Characters(c).DmgInRate = 0
                        Else
                            Raids(r).Bosses(b).Characters(c).DmgInRate = Math.Round(Raids(r).Bosses(b).Characters(c).CharaDmgIn / Raids(r).Bosses(b).RaidDmgIn * 100, 2)
                        End If
                        If Raids(r).Bosses(b).RaidEffHeal = 0 Then
                            Raids(r).Bosses(b).Characters(c).EffHealRate = 0
                        Else
                            Raids(r).Bosses(b).Characters(c).EffHealRate = Math.Round(Raids(r).Bosses(b).Characters(c).CharaEffHeal / Raids(r).Bosses(b).RaidEffHeal * 100, 2)
                        End If

                        If ExistHeal Then
                            Dim s As Long
                            For s = 0 To Raids(r).Bosses(b).Characters(c).Heals.Length - 1
                                If Raids(r).Bosses(b).Characters(c).CharaEffHeal = 0 Then
                                    Raids(r).Bosses(b).Characters(c).Heals(s).EffHealRate = 0
                                Else
                                    Raids(r).Bosses(b).Characters(c).Heals(s).EffHealRate = Math.Round(Raids(r).Bosses(b).Characters(c).Heals(s).EffHeal / Raids(r).Bosses(b).Characters(c).CharaEffHeal * 100, 2)
                                End If

                            Next
                        End If

                        If ExistDmgOut Then
                            Dim s As Long

                            If Raids(r).Bosses(b).Characters(c).CharaDmgOut = 0 Then
                                Raids(r).Bosses(b).Characters(c).DamageOut(s).DamageRate = 0
                            Else
                                Raids(r).Bosses(b).Characters(c).DamageOut(s).DamageRate = Math.Round(Raids(r).Bosses(b).Characters(c).DamageOut(s).Damage / Raids(r).Bosses(b).Characters(c).CharaDmgOut * 100, 2)
                            End If
                        End If

                        If ExistDmgIn Then
                            Dim s As Long
                            For s = 0 To Raids(r).Bosses(b).Characters(c).DamageIn.Length - 1
                                If Raids(r).Bosses(b).Characters(c).CharaDmgIn = 0 Then
                                    Raids(r).Bosses(b).Characters(c).DamageIn(s).DamageRate = 0
                                Else
                                    Raids(r).Bosses(b).Characters(c).DamageIn(s).DamageRate = Math.Round(Raids(r).Bosses(b).Characters(c).DamageIn(s).Damage / Raids(r).Bosses(b).Characters(c).CharaDmgIn * 100, 2)
                                End If
                            Next
                        End If
                    Next
                Next
            End If
        Next

        Return Raids
    End Function
End Class

